# frozen_string_literal: true

require 'watirspec_helper'

module Watir
  describe Element do
    before(:all) do
      browser.goto(WatirSpec.url_for('nested_elements.html'))
    end

    describe '#parent' do
      it 'gets immediate parent of an element by default' do
        expect(browser.div(id: 'first_sibling').parent.id).to eq 'parent'
        expect(browser.div(id: 'first_sibling').parent).to be_a Watir::HTMLElement
      end

      it 'accepts index argument' do
        expect(browser.div(id: 'first_sibling').parent(index: 2).id).to eq 'grandparent'
        expect(browser.div(id: 'first_sibling').parent(index: 2)).to be_a Watir::HTMLElement
      end

      it 'accepts tag_name argument' do
        expect(browser.div(id: 'first_sibling').parent(tag_name: 'div').id).to eq 'parent'
        expect(browser.div(id: 'first_sibling').parent(tag_name: 'div')).to be_a Watir::Div
      end

      it 'accepts custom tag_name argument' do
        expect(browser.div(id: 'regular_child').parent(tag_name: 'grandelement').id).to eq 'custom_grandparent'
        expect(browser.div(id: 'regular_child').parent(tag_name: 'grandelement')).to be_a Watir::HTMLElement
      end

      it 'accepts class_name argument' do
        expect(browser.div(id: 'first_sibling').parent(class_name: 'parent').id).to eq 'parent_span'
      end

      it 'accepts index and tag_name arguments' do
        expect(browser.div(id: 'first_sibling').parent(tag_name: 'div', index: 1).id).to eq 'grandparent'
        expect(browser.div(id: 'first_sibling').parent(tag_name: 'div', index: 1)).to be_a Watir::Div
      end

      it 'does not error when no parent element of an index exists' do
        expect(browser.body.parent(index: 2)).not_to exist
      end

      it 'does not error when no parent element of a tag_name exists' do
        expect(browser.div(id: 'first_sibling').parent(tag_name: 'table')).not_to exist
      end
    end

    describe '#siblings' do
      it 'gets collection of all siblings of an element' do
        expect(browser.div(id: 'second_sibling').siblings).to be_a Watir::HTMLElementCollection
        expect(browser.div(id: 'second_sibling').siblings.size).to eq 5
      end

      it 'accepts a tag name argument' do
        siblings = browser.div(id: 'second_sibling').siblings(tag_name: 'div')
        expect(siblings.size).to eq 3
        expect(siblings.all?(Watir::Div)).to be true
      end

      it 'accepts custom tag name argument' do
        siblings = browser.div(id: 'regular_child').siblings(tag_name: 'childelement')
        expect(siblings.size).to eq 3
        expect(siblings.all?(Watir::HTMLElement)).to be true
      end

      it 'accepts a class_name argument' do
        siblings = browser.div(id: 'second_sibling').siblings(class_name: 'b')
        expect(siblings.first).to be_a Watir::Div
        expect(siblings[0]).to be_a Watir::Div
        expect(siblings.size).to eq 2
        expect(siblings.all?(Watir::Div)).to be true
      end
    end

    describe '#following_sibling' do
      it 'gets immediate following sibling of an element by default' do
        expect(browser.div(id: 'first_sibling').following_sibling.id).to eq 'between_siblings1'
        expect(browser.div(id: 'first_sibling').following_sibling).to be_a Watir::HTMLElement
      end

      it 'accepts index argument' do
        expect(browser.div(id: 'first_sibling').following_sibling(index: 2).id).to eq 'between_siblings2'
        expect(browser.div(id: 'first_sibling').following_sibling(index: 2)).to be_a Watir::HTMLElement
      end

      it 'accepts tag_name argument' do
        expect(browser.div(id: 'first_sibling').following_sibling(tag_name: 'div').id).to eq 'second_sibling'
        expect(browser.div(id: 'first_sibling').following_sibling(tag_name: 'div')).to be_a Watir::Div
      end

      it 'accepts class_name argument' do
        expect(browser.div(id: 'first_sibling').following_sibling(class_name: 'b').id).to eq 'second_sibling'
      end

      it 'accepts index and tag_name arguments' do
        expect(browser.div(id: 'first_sibling').following_sibling(tag_name: 'div', index: 1).id).to eq 'third_sibling'
        expect(browser.div(id: 'first_sibling').following_sibling(tag_name: 'div', index: 1)).to be_a Watir::Div
      end

      it 'accepts text as Regexp' do
        expect(browser.div(id: 'first_sibling').following_sibling(text: /T/).id).to eq 'third_sibling'
      end

      it 'accepts text as String' do
        expect(browser.div(id: 'first_sibling').following_sibling(text: 'Third').id).to eq 'third_sibling'
      end

      it 'does not error when no next sibling of an index exists' do
        expect(browser.body.following_sibling(index: 1)).not_to exist
      end

      it 'does not error when no next sibling of a tag_name exists' do
        expect(browser.div(id: 'first_sibling').following_sibling(tag_name: 'table')).not_to exist
      end
    end

    describe '#following_siblings' do
      it 'gets collection of subsequent siblings of an element by default' do
        expect(browser.div(id: 'second_sibling').following_siblings).to be_a Watir::HTMLElementCollection
        expect(browser.div(id: 'second_sibling').following_siblings.size).to eq 2
      end

      it 'accepts tag_name argument' do
        expect(browser.div(id: 'second_sibling').following_siblings(tag_name: 'div').size).to eq 1
        expect(browser.div(id: 'second_sibling').following_siblings(tag_name: 'div').first).to be_a Watir::Div
      end

      it 'accepts class_name argument for single class' do
        expect(browser.div(id: 'second_sibling').following_siblings(class_name: 'b').size).to eq 1
        expect(browser.div(id: 'second_sibling').following_siblings(class_name: 'b').first).to be_a Watir::Div
      end

      it 'accepts class_name argument for multiple classes' do
        expect(browser.div(id: 'second_sibling').following_siblings(class_name: %w[a b]).size).to eq 1
        expect(browser.div(id: 'second_sibling').following_siblings(class_name: %w[a b]).first).to be_a Watir::Div
      end
    end

    describe '#previous_sibling' do
      it 'gets immediate preceeding sibling of an element by default' do
        expect(browser.div(id: 'third_sibling').previous_sibling.id).to eq 'between_siblings2'
        expect(browser.div(id: 'third_sibling').previous_sibling).to be_a Watir::HTMLElement
      end

      it 'accepts index argument' do
        expect(browser.div(id: 'third_sibling').previous_sibling(index: 2).id).to eq 'between_siblings1'
        expect(browser.div(id: 'third_sibling').previous_sibling(index: 2)).to be_a Watir::HTMLElement
      end

      it 'accepts tag_name argument' do
        expect(browser.div(id: 'third_sibling').previous_sibling(tag_name: 'div').id).to eq 'second_sibling'
        expect(browser.div(id: 'third_sibling').previous_sibling(tag_name: 'div')).to be_a Watir::Div
      end

      it 'accepts class_name argument' do
        expect(browser.div(id: 'third_sibling').previous_sibling(class_name: 'a').id).to eq 'between_siblings2'
      end

      it 'accepts index and tag_name arguments' do
        expect(browser.div(id: 'third_sibling').previous_sibling(tag_name: 'div', index: 1).id).to eq 'first_sibling'
        expect(browser.div(id: 'third_sibling').previous_sibling(tag_name: 'div', index: 1)).to be_a Watir::Div
      end

      it 'does not error when no next sibling of an index exists' do
        expect(browser.body.previous_sibling(index: 1)).not_to exist
      end

      it 'does not error when no next sibling of a tag_name exists' do
        expect(browser.div(id: 'third_sibling').previous_sibling(tag_name: 'table')).not_to exist
      end
    end

    describe '#previous_siblings' do
      it 'gets collection of previous siblings of an element by default' do
        expect(browser.div(id: 'second_sibling').previous_siblings).to be_a Watir::HTMLElementCollection
        expect(browser.div(id: 'second_sibling').previous_siblings.size).to eq 2
      end

      it 'accepts tag_name argument' do
        expect(browser.div(id: 'second_sibling').previous_siblings(tag_name: 'div').size).to eq 1
        expect(browser.div(id: 'second_sibling').previous_siblings(tag_name: 'div').first).to be_a Watir::Div
      end

      it 'accepts class_name argument' do
        expect(browser.div(id: 'second_sibling').previous_siblings(class_name: 'a').size).to eq 1
        expect(browser.div(id: 'second_sibling').previous_siblings(class_name: 'a').first.id).to eq 'between_siblings1'
      end
    end

    describe '#child' do
      it 'gets immediate child of an element by default' do
        expect(browser.div(id: 'parent').child.id).to eq 'first_sibling'
        expect(browser.div(id: 'parent').child).to be_a Watir::HTMLElement
      end

      it 'accepts index argument' do
        expect(browser.div(id: 'parent').child(index: 2).id).to eq 'second_sibling'
        expect(browser.div(id: 'parent').child(index: 2)).to be_a Watir::HTMLElement
      end

      it 'accepts tag_name argument' do
        expect(browser.div(id: 'parent').child(tag_name: 'span').id).to eq 'between_siblings1'
        expect(browser.div(id: 'parent').child(tag_name: 'span')).to be_a Watir::Span
      end

      it 'accepts custom tag_name argument' do
        expect(browser.element(id: 'custom_parent').child(tag_name: 'childelement').id).to eq 'custom_child'
        expect(browser.element(id: 'custom_parent').child(tag_name: 'childelement')).to be_a Watir::HTMLElement
      end

      it 'accepts class_name argument' do
        expect(browser.div(id: 'parent').child(class_name: 'b').id).to eq 'second_sibling'
      end

      it 'accepts index and tag_name arguments' do
        expect(browser.div(id: 'parent').child(tag_name: 'div', index: 1).id).to eq 'second_sibling'
        expect(browser.div(id: 'parent').child(tag_name: 'div', index: 1)).to be_a Watir::Div
      end

      it 'does not error when no next sibling of an index exists' do
        expect(browser.div(id: 'second_sibling').child(index: 1)).not_to exist
      end

      it 'does not error when no next sibling of a tag_name exists' do
        expect(browser.div(id: 'parent').child(tag_name: 'table')).not_to exist
      end
    end

    describe '#children' do
      it 'gets collection of children of an element by default' do
        expect(browser.div(id: 'parent').children).to be_a Watir::HTMLElementCollection
        expect(browser.div(id: 'parent').children.size).to eq 5
      end

      it 'accepts tag_name argument' do
        children = browser.div(id: 'parent').children(tag_name: 'div')
        expect(children.size).to eq 3
        expect(children.all?(Watir::Div)).to be true
      end

      it 'accepts custom tag_name argument' do
        children = browser.element(id: 'custom_parent').children(tag_name: 'childelement')
        expect(children.size).to eq 3
        expect(children.all?(Watir::HTMLElement)).to be true
      end

      it 'accepts a class_name argument' do
        children = browser.div(id: 'parent').children(class_name: 'b')
        expect(children.size).to eq 2
        expect(children.all?(Watir::Div)).to be true
      end
    end
  end
end
